﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.Serialization;
using System.Text;
using System.Threading.Tasks;
using System.Xml;
using System.Xml.Serialization;
using Windows.Data.Xml.Dom;
using Windows.Storage;
using Windows.Storage.Streams;

namespace iSciences.Data
{
    [XmlType("AppData")]
    public class AppData
    {
        public static Uri _baseUri = new Uri("ms-appx:///");
        private static List<Category> categories;

        public static List<Category> Categories
        {
            get { return categories; }
            set { categories = value; }
        }

        private static User currentUser;

        public static User CurrentUser
        {
            get { return AppData.currentUser; }
            set { AppData.currentUser = value; }
        }

        public AppData()
        {

        }

        //initialize application
        public async static Task Init()
        {
            //load user
            await AppData.DeserializeUser();
            if (CurrentUser == null)
                CurrentUser = await CreateUser();

            if (System.Net.NetworkInformation.NetworkInterface.GetIsNetworkAvailable())
            {
                //Load categories
                await AppData.LoadCategories();

                //save app
                await AppData.SerializeApp(AppData.Categories);
            }
            else
            {
                //load saved categories
                await AppData.DeserializeApp();
            }
        }

        public static void Quit()
        {
            AppData.SerializeUser(AppData.CurrentUser);
        }

        public static async Task<List<string>> GetUrls()
        {
            Uri uri = new Uri(_baseUri, @"\DataModel\database\streams.xml");
            StorageFile file = await Windows.Storage.StorageFile.GetFileFromApplicationUriAsync(uri);

            XmlDocument document = await XmlDocument.LoadFromFileAsync(file);
            List<String> urls = new List<string>();

            XmlNodeList files = document.SelectNodes("//stream");
            foreach (var item in files)
            {
                urls.Add(item.Attributes[1].InnerText);
            }

            return urls;
        }

        public static async Task LoadCategories()
        {
            List<string> _urls = await GetUrls();
            foreach (var url in _urls)
            {
                RSSStream rss = new RSSStream(url);
                await rss.ParseAsync();

                if (Categories == null)
                    Categories = new List<Category>();
                Categories.Add(rss.Category);
            }
        }

        public static List<Article> SearchArticles(string query)
        {
            List<Article> result = new List<Article>();
            List<Article> inter = new List<Article>();
            query = query.ToLower();

            foreach (var category in Categories)
            {
                inter = category.Articles.Where(a => a.Title.ToLower().Contains(query) || a.Subtitle.ToLower().Contains(query)).ToList();
                foreach (var item in inter)
                {
                    result.Add(item);
                }
            }
            return result;
        }

        public static List<string> GetArticlesSuggestion(string query)
        {
            List<string> result = new List<string>();
            List<string> inter = new List<string>();
            query = query.ToLower();

            foreach (var category in Categories)
            {
                inter = category.Articles.Where(a => a.Title.ToLower().Contains(query) || a.Subtitle.ToLower().Contains(query)).Select(a => a.Title).ToList();
                foreach (var item in inter)
                {
                    result.Add(item);
                }
            }
            return result;
        }

        public static List<Article> GetArticlesSuggestion()
        {
            List<Article> result = new List<Article>();
            List<Article> inter = new List<Article>();
            foreach (Preference query in CurrentUser.Prefrences)
            {
                foreach (var category in Categories)
                {
                    inter = category.Articles.Where(a => a.Title.ToLower().Contains(query.Key) || a.Subtitle.ToLower().Contains(query.Key)).ToList();
                    foreach (var item in inter)
                    {
                        result.Add(item);
                    }
                }
            }

            return result;
        }

        public static List<Article> SearchExactArticle(string query)
        {
            List<Article> result = new List<Article>();
            List<Article> inter = new List<Article>();
            query = query.ToLower();

            foreach (var category in Categories)
            {
                inter = category.Articles.Where(a => a.Title.ToLower().Contains(query) || a.Subtitle.ToLower().Contains(query)).ToList();
                foreach (var item in inter)
                {
                    result.Add(item);
                }
            }
            return result;
        }

        public static Article GetArticleById(string query)
        {
            Article article = null;
            foreach (var category in Categories)
            {
                article = category.Articles.Where(a => a.UniqueId.ToString() == query).SingleOrDefault();
                if (article != null)
                    break;
            }

            return article;
        }


        public static List<Article> GetTopFiveArticles()
        {
            List<Article> articles = new List<Article>();
            if (Categories != null)
            {
                foreach (var cat in Categories.Take(5))
                {
                    articles.Add(cat.Articles.ElementAt(0));
                }
            }
            return articles;
        }
        //--------------------------------------------------------------
        // User
        //--------------------------------------------------------------

        public static async void SerializeUser(User user)
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(User));
            StorageFile file = await ApplicationData.Current.RoamingFolder.CreateFileAsync("user.xml", CreationCollisionOption.ReplaceExisting);
            Stream stream = await file.OpenStreamForWriteAsync();
            serializer.WriteObject(stream, user);
            stream.Dispose();
        }

        public static async Task DeserializeUser()
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(User));
            StorageFile file = await ApplicationData.Current.RoamingFolder.CreateFileAsync("user.xml", CreationCollisionOption.OpenIfExists);
            Stream stream = await file.OpenStreamForReadAsync();
            if (stream.Length > 0)
            {
                User _user = (User)serializer.ReadObject(stream);
                CurrentUser = _user;
            }
            stream.Dispose();
        }

        //the first time when the user doesnt exists yet, we call this function
        public async static Task<User> CreateUser()
        {
            User user = new User();
            user.FirstNrame = await Windows.System.UserProfile.UserInformation.GetFirstNameAsync();
            user.LastName = await Windows.System.UserProfile.UserInformation.GetLastNameAsync();
            user.Login = await Windows.System.UserProfile.UserInformation.GetDisplayNameAsync();
            user.Email = string.Empty;
            user.Password = string.Empty;
            user.Group = new Group();
            user.Prefrences = new List<Preference>();
            user.Favoris = new List<Article>();
            return user;
        }


        //------------------------------------------------------------
        //Categories
        //------------------------------------------------------------

        public static async Task SerializeApp(List<Category> _categories)
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(List<Category>));
            StorageFile file = await ApplicationData.Current.RoamingFolder.CreateFileAsync("app.xml", CreationCollisionOption.ReplaceExisting);
            Stream stream = await file.OpenStreamForWriteAsync();
            serializer.WriteObject(stream, _categories);
            stream.Dispose();
        }

        public static async Task DeserializeApp()
        {
            DataContractSerializer serializer = new DataContractSerializer(typeof(List<Category>));
            StorageFile file = await ApplicationData.Current.RoamingFolder.CreateFileAsync("app.xml", CreationCollisionOption.OpenIfExists);
            Stream stream = await file.OpenStreamForReadAsync();
            if (stream.Length > 0)
            {
                List<Category> _categories = (List<Category>)serializer.ReadObject(stream);
                Categories = _categories;
            }
            stream.Dispose();
        }

        //--------------------------------------------------------------
        // gestion favoris
        //-------------------------------------------------------------
        public static void AddFavorite(Article article)
        {
            CurrentUser.Favoris.Add(article);
        }

    }
}
